package org.zjvis.graph.analysis.service;

import io.minio.*;
import io.minio.messages.Item;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MinioService {
    private static final Logger logger = LoggerFactory.getLogger(MinioService.class);

    @Value("${minio.http}")
    private String httpUrl;

    @Value("${minio.key}")
    private String key;

    @Value("${minio.psw}")
    private String psw;

    private MinioClient minioClient;

    @PostConstruct
    private void init() throws KeyManagementException {
        OkHttpClient okHttpClient = MinioService.getUnsafeOkHttpClient();
        minioClient = MinioClient.builder()
                .endpoint(httpUrl)
                .credentials(key, psw)
                .httpClient(okHttpClient)
                .build();
    }

    public InputStream getObject(String bucket, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucket)
                .object(objectName)
                .build());
    }

    public List<String> listObjects(String bucket, String prefix) throws Exception {
        List<Item> items = new ArrayList<>();
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).recursive(true).prefix(prefix).build());
        results.forEach(result -> {
            try {
                items.add(result.get());
            } catch (Exception e) {
                logger.error("listObjects error");
            }
        });
        logger.info("listObjects size: {}", items.size());
        items.sort(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o2.lastModified().compareTo(o1.lastModified());
            }
        });
        return items.stream().map(Item::objectName).map(s->s.replaceFirst(prefix, "")).collect(Collectors.toList());
    }

    //取消SSL验证,解决SSLHandshakeException
    public static OkHttpClient getUnsafeOkHttpClient() throws KeyManagementException {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);

            builder.hostnameVerifier((s, sslSession) -> true);
            return builder.build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void queryOneFile(String bucket, String prefix) {
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucket).prefix(prefix).maxKeys(1).build());
    }
}
